/* 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Title : com.Angaliwa.UserDock
Author : Dave Jansen -- Zenitum
URL : http://www.zenitum.com/

Description : Creates an horizontal or vertical dock
			  which contains user icons. Normally works
			  together with Angaliwa's Users module, but
			  can accept user data from other sources, 
			  too. Requires at least user.id, user.name
			  and preferable user.position to be present.
			  Without the latter, the user's position
			  will be decided based on it's location 
			  within the array.

History		: v1.1.0090826 Rewrote large parts of the 
			  UserDock. It now no longer uses an HBox
			  or VBox, it instead uses a custom-written
			  container based on Canvas which allows us
			  to use a lot more visual goodness, including
			  add/remove animations, re-positioning and
			  smart resizing based.
			  
			  v1.0.090720 Initial version

Created 	: July 20th, 2009

Version		: 1.1
Compatibility: 1.1

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
*/

package com.Angaliwa{
	import mx.containers.Canvas;
	import mx.events.FlexEvent;
	
	public class UserDock{
		
					// Angaliwa modules
		private var daisyChain:DaisyChain = new DaisyChain(this),
					settings:Settings =  new Settings(),
					resizeHandler:ResizeHandler =  Core.g('resizeHandler'),
					scaleHandler:Scaler = new Scaler(this,resizeHandler),
					
					// Module-related containers
					parentObject:*,
					userIcon:*,
					users:Array = [],
					excluded:Array = [];
		
		// Temp.
		public var	dock:Canvas;
		
		/*
		 * Summary:      	Initializes the UserDock module
		 					and creates the dock.
		 * Return:       	Void
		 * Version:   	 	1.1
		 * Compatibility:	1.0
		 */
		public function UserDock(parent:*, userIconObject:Object, userList:*, customSettings:Object=undefined){
			parentObject = parent;
			userIcon = userIconObject;
			
			// Set up the default settings and
			// custom settings, if available.
			settings.setDefaults({
						width: '100%',
						height: 150,
						orientation: 'horizontal',
						horizontal: 'left',
						vertical: 'bottom',
						objectSpacing: 15,
						userObjectNameStart: 'user',
						userObjectNameEnd: ''
					})
					.add(customSettings);
			
			
			// Create the dock container
			dock = new Canvas();
			parent.addChild(dock);
			
			// Apply any styles that may have been specified
			// to the dock.
			Toolbox.applyStyles(dock,settings.get('styles')); 
			
			// Whenever something happens to the dock (or it's
			// children), we'll call for dockUpdate to walk
			// through the icons and make sure they all
			// (re-)position accordingly.
			dock.addEventListener(FlexEvent.UPDATE_COMPLETE, updateDock);
			
			if(resizeHandler){
				resizeHandler.setSize(dock, settings.get('width'), settings.get('height'))
							 .setPosition(dock, settings.get('horizontal'),
							 					settings.get('vertical'));
			}
			
			// Needs more work!
			userList.daisyChain.a(['userJoined','selfJoined'], add)
						.daisyChain.a(['userLeft','selfLeft'], del)
						.daisyChain.a('init', function(users:Array):void{
							for(var i:int=0; i < users.length; i++){
								add(users[i]);
							}
						});
		}
		
		/*
		 * Summary:      	Adds an user icon to the dock at the
		 					specified location, or if not specified
		 					at the next logical location. 
		 					The object u needs to have at least an
		 					'id' available, and most often also
		 					requires 'name' to be present.
		 * Return:       	UserDock (this)
		 * Version:   	 	1.0
		 * Compatibility:	1.0
		 */
		public function add(u:Object):UserDock{
			trace('[UserDock] [ADD] Preparing to add user '+u.id+' ('+u.name+') to '+dock);
			
			var allowed:Boolean=true,
				only:Object = settings.get('only');
				
			if(only){
				for(var c:String in only){
					trace('[UserDock] [ADD] Checking '+c+': '+only[c]+' vs. '+u[c]);
					
					/*
					if(only[c] == false && !u.hasOwnProperty(c)){
						
					} else 
					*/
					
					if(only[c].toString() !== u[c].toString()){
						trace('[UserDock] [ADD] Disallowed, variables do not match.');
						allowed=false;
					}
				}
			}
			
			if(allowed){
				trace('[UserDock] [ADD] User is allowed to be shown in this dock.');
				
				var icon:* = new userIcon;
				icon.d = u;
				icon.id,icon.name = settings.get('userObjectNameStart')
									+u.id
									+settings.get('userObjectNameEnd');
				//icon.visible = false;
				
				dock.addChild(icon);
				
				/*
				var pos:int = (u.hasOwnProperty('position')) ? u.position : users.length,
					x:int = 0;
				
				for(var i:int=0; i < users.length; i++){
					if(i == pos) // Stop the loop.
						i=users.length;
					else{
						trace(users[i].obj.width);
						x += users[i].obj.width+settings.get('objectSpacing');
					}
				}
				
				// test.
				icon.x = x;
				*/
				
				users.push({id:u.id, u:u,obj:icon});
			}
			else{
				trace('[UserDock] [ADD] User '+u.id+' ('+u.name+') not allowed as per this dock\'s settings. ('+dock);
			}
					
			return this;
		}
		
		/*
		 * Summary:      	Finds and returns an user icon from the dock.
		 * Return:       	Object
		 * Version:   	 	1.0
		 * Compatibility:	1.0
		 */
		public function get(id:int):*{
			var obj:* = dock.getChildByName(settings.get('userObjectNameStart')+id);
			return obj;
		}
		
		/*
		 * Summary:      	Removes an user icon from the dock.
		 * Return:       	Boolean
		 * Version:   	 	1.0
		 * Compatibility:	1.0
		 */
		public function del(u:Object):Boolean{
			var obj:* = dock.getChildByName(settings.get('userObjectNameStart')+u.id);
			
			// If the user icon has it's own remove function, we'll make
			// use of that. If not, we'll delete it right away.
			if(obj && obj.hasOwnProperty('remove') && obj.remove is Function) obj.remove();
				else if(obj) dock.removeChild(obj);
			
			return false;
		}
		
		private function updateDock(e:FlexEvent=undefined):void{
			var refDock:Canvas = (e) ? e.target as Canvas : dock;
			
			for(var i:int=0; i < refDock.getChildren().length; i++){
				var crnt:Object = refDock.getChildAt(i),
					prev:Object = (i>0) ? refDock.getChildAt(i-1) : null,
					destX:Number,destY:Number;
				
				destX = (prev) ? Number(prev.x+prev.width+settings.get('objectSpacing')) : 0;
				crnt.x = destX;
				
				trace('DOCK: #'+i+': '+destX);
			}
		}
	}
}